﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows;
using SHomeWorkshop.LunarConcept.Tools;
using System.Windows.Controls;
using System.Xml;
using System.Windows.Input;
using System.Windows.Media;
using SHomeWorkshop.LunarConcept.Adorners;
using SHomeWorkshop.LunarConcept.Enums;
using System.Windows.Media.Imaging;
using SHomeWorkshop.LunarConcept.Converters;
using SHomeWorkshop.LunarConcept.Controls;
using SHomeWorkshop.LunarConcept.Widgets.Interfaces;
using SHomeWorkshop.LunarMind;

namespace SHomeWorkshop.LunarConcept.Widgets
{
    /// <summary>
    /// 创建时间：2012年1月2日
    /// 创建者：  杨震宇
    /// 
    /// 主要用途：为可以内嵌内容（Content）的部件提供的基类。这类部件需要自定义左上角的坐标。
    ///           目前，Content部件包括：TextArea/PictureBox/Group。二○一二年六月八日
    /// </summary>
    public abstract class ContentWidget : Widget, ICanBeLinkedWidget, ITextRotate, IWidgetPadding
    {
        #region 构造方法=====================================================================================================

        /// <summary>
        /// [构造方法]此类只是中间类，不作为任何具体的类。不应直接调用此构造方法。
        /// </summary>
        /// <param name="masterPageEditor">所属的PageEditor。</param>
        public ContentWidget(Controls.PageEditorReader masterPageEditor)
            : base(masterPageEditor)
        {
            this.layerIndex = WidgetLayerIndex.ContentWidget;
            RefreshLayerIndex();

            this.Child = this.mainBorder;
            
            this.maskAdorner = new MaskAdorner(this);
            this.AdornerLayer.Add(this.maskAdorner);//注意它要在linkerAdorner底层。

            //外框装饰器
            this.outerBorderAdorner = new OuterBorderAdorner(this.mainBorder, this);
            this.AdornerLayer.Add(this.outerBorderAdorner);
            
            this.commentAdorner = new CommentAdorner(this.mainBorder, this) { Visibility = System.Windows.Visibility.Collapsed };//默认不显示。
            this.AdornerLayer.Add(this.commentAdorner);//这个要在各具体部件类中添加。

            this.hyperLinkAdorner = new HyperLinkAdorner(this.mainBorder, this) { Visibility = Visibility.Collapsed };
            this.hyperLinkAdorner.MouseLeftButtonUp += new MouseButtonEventHandler(hyperLinkAdorner_MouseLeftButtonUp);
            this.AdornerLayer.Add(this.hyperLinkAdorner);
        }

        #endregion

        #region 字段与属性===================================================================================================

        /// <summary>
        /// [只读]返回右下角坐标。
        /// </summary>
        public override Point BottomRight
        {
            get
            {
                Size size = this.mainBorder.RenderSize;
                if (size.Width == 0 || size.Height == 0)
                {
                    this.InvalidateArrange();//没这个就不成。
                    this.UpdateLayout();
                    size = this.mainBorder.RenderSize;
                }

                return new Point(location.X + size.Width, location.Y + size.Height);
            }
        }

        /// <summary>
        /// 下备注文本装饰器。
        /// </summary>
        private WidgetCommentAdorner commentBottomAdorner = null;

        /// <summary>
        /// 上备注文本装饰器。
        /// </summary>
        private WidgetCommentAdorner commentTopAdorner = null;

        private string commentBottomText = string.Empty;
        /// <summary>
        /// [读写]部件下注释文本。
        /// </summary>
        [Tools.LunarProperty("CommentBottomText", PropertyDateType.String)]
        public string CommentBottomText
        {
            get { return commentBottomText; }
            set
            {
                commentBottomText = value;
                if (this.xmlData != null)
                {
                    this.xmlData.SetAttribute(XmlTags.CommentBottomTextTag, value);
                }

                this.RefreshCustomCommentText();
            }
        }

        private string commentTopText = string.Empty;
        /// <summary>
        /// [读写]部件上注释文本。
        /// </summary>
        [Tools.LunarProperty("CommentTopText", PropertyDateType.String)]
        public string CommentTopText
        {
            get { return commentTopText; }
            set
            {
                commentTopText = value;
                if (this.xmlData != null)
                {
                    this.xmlData.SetAttribute(XmlTags.CommentTopTextTag, value);
                }

                this.RefreshCustomCommentText();
            }
        }

        /// <summary>
        /// [只读]表示当前部件是否被某个连接线挂接着。
        /// </summary>
        public bool IsLinked
        {
            get
            {
                if (this.masterEditor == null) return false;

                foreach (UIElement ue in this.masterEditor.Children)
                {
                    ILinkableLine linkedLine = ue as ILinkableLine;
                    if (linkedLine == null) continue;

                    if (linkedLine.StartMasterId == this.id || linkedLine.EndMasterId == this.id) return true;
                }

                return false;
            }
        }

        protected Point location = new Point();
        /// <summary>
        /// 部件左上角位置。
        /// </summary>
        [LunarConcept.Tools.LunarProperty("Location", Enums.PropertyDateType.Point)]
        public Point Location
        {
            get { return location; }
            set
            {
                location = value;
                if (this.xmlData != null)
                {
                    this.xmlData.SetAttribute(XmlTags.LocationTag, location.ToString());
                }

                this.RefreshLocation();
            }
        }

        protected OuterBorderAdorner outerBorderAdorner;
        /// <summary>
        /// [只读]外框装饰器。
        /// </summary>
        public OuterBorderAdorner OuterBorderAdorner
        {
            get { return outerBorderAdorner; }
        }

        private OuterBorderType outerBorderType = OuterBorderType.Rect;
        /// <summary>
        /// [读写]外框类型。默认应矩形，不使用装饰器呈现；除矩形外其它外框以装饰器呈现。
        /// </summary>
        [Tools.LunarProperty("OuterBorderType", PropertyDateType.OuterBorderType)]
        public OuterBorderType OuterBorderType
        {
            get { return outerBorderType; }
            set
            {
                outerBorderType = value;
                if (this.xmlData != null)
                {
                    this.xmlData.SetAttribute(XmlTags.OuterBorderTypeTag, outerBorderType.ToString());
                }

                RefreshOuterBorderType();
            }
        }
        
        protected Border mainBorder = new Border() { Padding = new Thickness(10), Cursor = Cursors.Hand };
        /// <summary>
        /// [只读]主Border。用以承载其它部件内嵌内容。
        /// </summary>
        public Border MainBorder
        {
            get { return mainBorder; }
        }

        private MaskType mask = MaskType.None;
        /// <summary>
        /// [读写]遮罩类型。
        /// </summary>
        [Tools.LunarProperty("Mask", PropertyDateType.MaskType)]
        public MaskType Mask
        {
            get { return mask; }
            set
            {
                mask = value;
                if (this.xmlData != null)
                {
                    this.xmlData.SetAttribute(XmlTags.MaskTag, value.ToString());
                }

                this.maskAdorner.InvalidateVisual();
            }
        }

        /// <summary>
        /// 遮罩装饰器。
        /// </summary>
        private MaskAdorner maskAdorner;

        public override System.Windows.Rect OuterRect
        {
            get
            {
                Rect r = new Rect(TopLeft, BottomRight);
                return r;
            }
        }

        /// <summary>
        /// 部件正在被拖动时的外边框。
        /// </summary>
        public Rect MovingRect
        {
            get
            {
                Rect rect = new Rect(Canvas.GetLeft(this), Canvas.GetTop(this),
                    this.ActualWidth, this.ActualHeight);

                return rect;
            }
        }
        
        private double textRotateAngle = 0;
        /// <summary>
        /// [读写]文本旋转角度。取值范围：[-180,180]。
        /// </summary>
        [Tools.LunarProperty("TextRotateAngle", PropertyDateType.Double)]
        public double TextRotateAngle
        {
            get { return textRotateAngle; }
            set
            {
                if (value > 180)
                {
                    textRotateAngle = 180;
                }
                else if (value < -180)
                {
                    textRotateAngle = -180;
                }
                else
                {
                    textRotateAngle = value;
                }

                if (this.xmlData != null)
                {
                    this.xmlData.SetAttribute(XmlTags.TextRotateAngleTag, textRotateAngle.ToString());
                }

                this.RefreshTextRotateAngle();
            }
        }

        public override Point TopLeft
        {
            get { return location; }
        }

        /// <summary>
        /// [读写]此属性是Location属性的别名。
        /// </summary>
        [Tools.LunarProperty("StartPoint", PropertyDateType.Point)]
        public Point StartPoint
        {
            get { return location; }
            set { Location = value; }
        }

        /// <summary>
        /// [事实只读]ContentWidget是自适应大小的，因而此属性虽然可以赋值，但赋值后什么都不会发生。
        /// 　　　　　——此属性可写，只是因为ICanBeLinkedWidget接口的需要。InsertRelation命令依赖此属性。2012年6月1日
        /// 　　　　　此属性返回的值与BottomRight的返回值相同。
        /// </summary>
        public Point EndPoint
        {
            get { return BottomRight; }
            set { return; }
        }

        //2012年6月26日此属性被取消，改用WidgetLineWidth属性。
        //protected double widgetBorderWidth = 0;
        ///// <summary>
        ///// [读写]部件边框宽度。默认为2。
        ///// </summary>
        //[Tools.LunarProperty("WidgetBorderWidth", PropertyDateType.Double)]
        //public double WidgetBorderWidth
        //{
        //    get { return widgetBorderWidth; }
        //    set
        //    {
        //        widgetBorderWidth = value;
        //        if (this.xmlData != null)
        //        {
        //            this.xmlData.SetAttribute(XmlTags.WidgetBorderWidth, value.ToString());
        //        }
        //        this.RefreshWidgetBorderWidth();
        //    }
        //}

        protected Thickness widgetPadding = new Thickness(0);
        /// <summary>
        /// [读写]部件内部空隙宽。默认值为0。
        /// </summary>
        [Tools.LunarProperty("WidgetPadding", PropertyDateType.Thickness)]
        public Thickness WidgetPadding
        {
            get { return widgetPadding; }
            set
            {
                widgetPadding = value;
                if (this.xmlData != null)
                {
                    this.xmlData.SetAttribute(XmlTags.WidgetPadding, masterEditor.ThickConverter.ConvertToString(value));
                }
                this.RefreshWidgetPadding();
            }
        }
        #endregion

        #region 方法=========================================================================================================

        /// <summary>
        /// 生成部件的内容。此方法应由派生类在重写时调用。
        /// </summary>
        public override void Build()
        {
            base.Build();

            try
            {
                XmlAttribute attrMask = this.xmlData.GetAttribute(XmlTags.MaskTag);
                if (attrMask != null)
                {
                    this.mask = (MaskType)Enum.Parse(typeof(MaskType), attrMask.Value);
                }

                XmlAttribute attrCommentBottomText = this.xmlData.GetAttribute(XmlTags.CommentBottomTextTag);
                if (attrCommentBottomText != null)
                {
                    this.commentBottomText = attrCommentBottomText.Value;
                }

                XmlAttribute attrCommentTopText = this.xmlData.GetAttribute(XmlTags.CommentTopTextTag);
                if (attrCommentTopText != null)
                {
                    this.commentTopText = attrCommentTopText.Value;
                }
                
                XmlAttribute attrLocation = this.xmlData.GetAttribute(XmlTags.LocationTag);
                if (attrLocation != null)
                {
                    this.location = Point.Parse(attrLocation.Value);
                }

                XmlAttribute attrTextRotateAngle = this.xmlData.GetAttribute(XmlTags.TextRotateAngleTag);
                if (attrTextRotateAngle != null)
                {
                    this.textRotateAngle = double.Parse(attrTextRotateAngle.Value);
                }

                XmlAttribute attrOuterBorderType = this.xmlData.GetAttribute(XmlTags.OuterBorderTypeTag);
                if (attrOuterBorderType != null)
                {
                    this.outerBorderType = (Enums.OuterBorderType)Enum.Parse(typeof(Enums.OuterBorderType), attrOuterBorderType.Value);
                }

                this.RefreshTextRotateAngle();
                this.RefreshOuterBorderType();
                this.RefreshLocation();
                this.RefreshMask();
                this.RefreshCustomCommentText();

                //到ContentWidget为止，这个类分支已经实现了所需要的与WidgetStyle相关的所有属性。
                //上层的Widget已经实现了WidgetForeColor、IsShadowVisiable和WidgetOpacity并调用了相应的Refreshxxx()方法。
                //ContentWidget不需要WidgetStyle中的LineDash和Arrows属性。
                //因此调用，
                this.RefreshWidgetLineColor();
                this.RefreshWidgetLineWidth();
                this.RefreshWidgetBackColor();
                this.RefreshWidgetPadding();

            }
            catch (Exception ex)
            {
                MessageBox.Show("　　构造内容部件时出现错误。异常信息如下：\r\n" + ex.Message + "\r\n" + ex.StackTrace,
                    Globals.AppName, MessageBoxButton.OK, MessageBoxImage.Warning);
                return;
            }
        }
                
        /// <summary>
        /// 取与自身挂接的连接线。
        /// </summary>
        /// <returns>可能返回null。</returns>
        public List<ILinkableLine> GetLinkedLines()
        {
            if (this.masterEditor == null) return null;

            List<Widget> widgets = new List<Widget>();
            widgets.Add(this);

            return this.masterEditor.GetLinkedLines(widgets);
        }
        
        public override void RefreshIsShadowVisible()
        {
            if (isShadowVisible)
            {
                //this.mainTextPanel.Effect =//保持文本清晰
                this.mainBorder.Effect = Widget.ShadowEffect;
            }
            else
            {
                //this.mainTextPanel.Effect =
                this.mainBorder.Effect = null;
            }
        }

        /// <summary>
        /// Location设置好后，刷新部件位置。
        /// </summary>
        public override void RefreshLocation()
        {
            Canvas.SetLeft(this, location.X);
            Canvas.SetTop(this, location.Y);

            this.RefreshCommentText();
            this.RefreshHyperLinkText();
        }

        /// <summary>
        /// 刷新顶注释与底注释文本。——这与所有部件均支持的备注文本不同。
        /// </summary>
        public void RefreshCustomCommentText()
        {
            if (this.commentTopText != null && this.commentTopText.Length > 0)
            {
                if (this.commentTopAdorner == null)
                {
                    this.commentTopAdorner = new WidgetCommentAdorner(this.mainBorder,
                        this, WidgetCommentAdorner.Location.Top);
                    this.AdornerLayer.Add(this.commentTopAdorner);
                }

            }

            if (this.commentTopAdorner != null)
            {
                this.commentTopAdorner.InvalidateVisual();
            }

            if (this.commentBottomText != null && this.commentBottomText.Length > 0)
            {
                if (this.commentBottomAdorner == null)
                {
                    this.commentBottomAdorner = new WidgetCommentAdorner(this.mainBorder,
                        this, WidgetCommentAdorner.Location.Bottom);
                    this.AdornerLayer.Add(this.commentBottomAdorner);
                }

            }

            if (this.commentBottomAdorner != null)
            {
                this.commentBottomAdorner.InvalidateVisual();
            }
        }

        /// <summary>
        /// 刷新遮罩状态。
        /// </summary>
        public void RefreshMask()
        {
            this.maskAdorner.InvalidateVisual();
        }

        /// <summary>
        /// 刷新外框类型。
        /// </summary>
        public void RefreshOuterBorderType()
        {
            switch (this.outerBorderType)
            {
                case Enums.OuterBorderType.Rect:
                    {
                        this.mainBorder.BorderBrush = this.widgetLineColor;
                        this.outerBorderAdorner.Visibility = Visibility.Collapsed;
                        return;//直接返回
                    }
                default:
                    {
                        this.mainBorder.BorderBrush = Brushes.Transparent;//其它全不显示。
                        this.outerBorderAdorner.Visibility = Visibility.Visible;
                        break;
                    }
            }

            if (this.outerBorderAdorner != null)
            {
                this.outerBorderAdorner.InvalidateVisual();
            }
        }

        /// <summary>
        /// 刷新文本区旋转角度。
        /// </summary>
        public void RefreshTextRotateAngle()
        {
            if (this.mainTextPanel.RenderTransformOrigin != DefaultRenderCenter)
            {
                this.mainTextPanel.RenderTransformOrigin = DefaultRenderCenter;
            }

            if (this.textRotateAngle == 0)
            {
                this.mainTextPanel.RenderTransform = DefaultRotateTransform;
            }
            else
            {
                this.mainTextPanel.RenderTransform = new RotateTransform(textRotateAngle);
            }
        }

        /// <summary>
        /// WidgetBackground属性值改变时会调用此方法刷新部件的背景色。
        /// ——亦可根据需要调用。
        /// ——默认直接改变mainBorder的背景色。派生类可自行定义行为。
        /// </summary>
        public override void RefreshWidgetBackColor()
        {
            if (this.mainBorder != null)
                this.mainBorder.Background = widgetBackColor;
            this.RefreshMask();
        }

        /// <summary>
        /// WidgetBorderBrush属性值改变时会调用此方法刷新部件边框色。
        /// ——亦可根据需要调用。
        /// ——默认直接更改mainBorder的边框色。派生类可自行定义行为。
        /// </summary>
        public override void RefreshWidgetLineColor()
        {
            switch (this.outerBorderType)
            {
                case Enums.OuterBorderType.Rect:
                    {
                        if (this.mainBorder != null)
                            this.mainBorder.BorderBrush = WidgetLineColor;
                        break;
                    }
                default:
                    {
                        if (this.mainBorder != null)
                            this.mainBorder.BorderBrush = Brushes.Transparent;
                        break;
                    }
            }

            this.RefreshOuterBorderType();
        }

        //2012年6月26日，取消WidgetBorderWidth属性，改用WidgetLineWidth属性。
        //public virtual void RefreshWidgetBorderWidth()
        //{
        //    if (this.mainBorder != null)
        //        this.mainBorder.BorderThickness = new Thickness(this.widgetBorderWidth);
        //}

        public override void RefreshWidgetLineWidth()
        {
            if (this.mainBorder != null)
                this.mainBorder.BorderThickness = new Thickness(this.widgetLineWidth);
        }

        public override void RefreshWidgetForeColor()
        {
            base.RefreshWidgetForeColor();

            this.RefreshMask();
        }

        public virtual void RefreshWidgetPadding()
        {
            if (this.mainBorder != null)
                this.mainBorder.Padding = this.widgetPadding;
        }

        #endregion
    }
}
